import { effect, isSingal } from "./singal";
import { call, isFalsity } from "./utils";

let current;
function wrapChild(child) {
  if (["string", "number"].includes(typeof child)) {
    return document.createTextNode(child);
  } else if (child instanceof Node) {
    return child;
  }
}

export function attrs(obj) {
  const el = current;
  effect(() => {
    if (!el) return;
    const prop = call(obj);
    for (let key in prop) {
      el.setAttribute(key, call(prop[key]));
    }
  });
}
export function cls(obj) {
  const el = current;
  effect(() => {
    if (!el) return;
    let list = call(obj);
    if (Array.isArray(list)) {
      list = list.map(call).filter(Boolean);
    } else {
      list = Object.keys(list).filter((p) => call(list[p]));
    }
    el.className = [...new Set(list.filter(Boolean))].join(" ");
  });
}

export function on(obj) {
  const el = current;
  const prev = {};
  effect(() => {
    if (!el) return;
    Object.keys(prev).forEach((key) => {
      el.removeEventListener(key, prev[key]);
    });
    const prop = call(obj);
    for (let key in prop) {
      if (typeof prop[key] === "function") {
        prev[key] = prop[key];
        el.addEventListener(key, prop[key]);
      }
    }
  });
}

export function createTag(name, namespaceURI) {
  return function tag(init) {
    const el = namespaceURI
      ? document.createElementNS(namespaceURI, name)
      : document.createElement(name);

    const _el = current;

    if (_el) {
      _el.appendChild(el);
    }
    current = el;

    if (typeof init === "function") {
      init();
    } else {
    }
    current = _el;

    return el;
  };
}
export const div = createTag("div");
export const span = createTag("span");
export const button = createTag("button");
export const p = createTag("p");
export const img = createTag("img");
export const ul = createTag("ul");
export const ol = createTag("ol");
export const li = createTag("li");
export const a = createTag("a");
export const svg = createTag("svg", "http://www.w3.org/2000/svg");
export const text = (val) => {
  const node = document.createTextNode("");
  const el = current;
  if (el) {
    el.appendChild(node);
  }
  effect(() => {
    node.textContent = call(val);
  });
};

export const when = (fn) => {
  const el = current;
  const marker = document.createComment("placeholder");
  if (el) {
    el.appendChild(marker);
  }
  let prevEl = marker;
  effect(() => {
    const node = wrapChild(call(fn));
    if (node) {
      if (prevEl) {
        prevEl.replaceWith(node);
      } else {
        marker.replaceWith(node);
      }
    } else {
      if (prevEl) {
        prevEl.replaceWith(marker);
      }
    }
    prevEl = node;
  });
};

export function wrap(fn) {
  if (!current) return;
  const marker = document.createComment("wrap");
  current.appendChild(marker);
  effect(() => {
    const result = fn();
  });
}
